package org.example.service.impl;

import org.example.entity.auth.Account;
import org.example.mapper.UserMapper;
import org.example.service.AuthorizeService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Lazy;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.mail.MailException;
import org.springframework.mail.MailSender;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Optional;
import java.util.Random;
import java.util.concurrent.TimeUnit;

@Service
public class AuthorizeServiceImpl implements AuthorizeService {

    private static final Logger logger = LoggerFactory.getLogger(AuthorizeService.class);

    @Value("${spring.mail.username}")
    String from;
    @Resource
    UserMapper mapper;

    @Resource
    MailSender mailSender;

    @Resource
    StringRedisTemplate template;

    @Lazy
    @Resource
    BCryptPasswordEncoder encoder;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        if (username == null) {
            throw new UsernameNotFoundException("用户名不能为空");
        }
        logger.info("【进入 loadUserByUsername】请求用户名: {}", username); // 添加日志

        Account account = mapper.findAccountByNameOrEmail(username);
        if (account == null) {
            throw new UsernameNotFoundException("用户名或密码错误");
        }
        logger.info("【找到用户】用户名: {}", account.getUsername());
        return User.withUsername(account.getUsername())
                .password(account.getPassword())
                .roles("user")
                .build();
    }

    /**
     * 发送邮箱
     *
     * @param email
     * @return 1.先生成对应的验证码
     * 2.把邮箱和对应的验证码直接放到redis里面（过期时间三分钟，如果此时重新发送邮件，只要剩余时间低于2分钟，就可以重新发送一次）
     * 3.发送验证码到指定邮箱
     * 4.如果发送失败，把redis里面插入的删除
     * 5.用户在注册时，再从redis里取出对应键值对，看验证码是否一致
     */
    @Override
    public String sendValitateEmail(String email, String sessionId, boolean hasAccount) {
        String key = "email:" + sessionId + ":" + email + ":" + hasAccount;
        if (Boolean.TRUE.equals(template.hasKey(key))) {
            Long expire = Optional.ofNullable(template.getExpire(key, TimeUnit.SECONDS)).orElse(0L);//获取key的有效时间
            if (expire > 120) {
                return "请求频繁，请稍后重试！";
            }
        }
        Account account = mapper.findAccountByNameOrEmail(email);
        if (hasAccount && account == null) {
            return "没有此邮箱地址的用户";
        }
        if (!hasAccount && account != null) {
            return "此邮箱已被其他用户注册！";
        }
        Random random = new Random();
        int code = random.nextInt(899999) + 100000;//保证生成的验证码为六位数
        SimpleMailMessage message = new SimpleMailMessage();
        message.setFrom(from);
        message.setTo(email);
        message.setSubject("您的验证邮件");
        message.setText("验证码是：" + code);
        try {
            mailSender.send(message);//发送邮件

            template.opsForValue().set(key, String.valueOf(code), 3, TimeUnit.MINUTES);//存入redis，设置三分钟的过期时间

            return null;
        } catch (MailException e) {
            e.printStackTrace();
            return "邮件发送失败，请检查邮箱地址是否有效。";
        }
    }

    /**
     * 注册用户
     *
     * @param username
     * @param password
     * @param email
     * @param code
     * @param sessionId
     * @return
     */
    @Override
    public String validateAndRegister(String username, String password, String email, String code, String sessionId) {
        String key = "email:" + sessionId + ":" + email + "：false";
        if (Boolean.TRUE.equals(template.hasKey(key))) {
            String s = template.opsForValue().get(key);
            if (s == null) {
                return "邮箱验证码已经过期，请重新发送";
            }
            if (s.equals(code)) {
                Account account = mapper.findAccountByNameOrEmail(username);
                if(account != null){
                    return "此用户名已经被注册，请更换用户名！";
                }
                template.delete(key);
                password = encoder.encode(password);
                if (mapper.createAccount(username, password, email) > 0) {
                    return null;
                } else {
                    return "发生内部错误，请联系管理员";
                }
            } else {
                return "邮箱验证码错误，请检查";
            }
        } else {
            return "请先发送邮箱验证码";
        }
    }

    /**
     * 验证邮箱
     *
     * @param email
     * @param code
     * @param sessionId
     * @return
     */
    @Override
    public String validateOnly(String email, String code, String sessionId) {
        String key = "email:" + sessionId + ":" + email + "：true";
        if (Boolean.TRUE.equals(template.hasKey(key))) {
            String s = template.opsForValue().get(key);
            if (s == null) {
                return "邮箱验证码已经过期，请重新发送";
            }
            if (s.equals(code)) {
                template.delete(key);
                return null;
            } else {
                return "邮箱验证码错误，请检查";
            }
        } else {
            return "请先发送邮箱验证码";
        }
    }

    /**
     * 重置密码
     *
     * @param email
     * @param password
     * @return
     */
    @Override
    public boolean resetPassword(String email, String password) {
        password = encoder.encode(password);
        return mapper.resetPasswordByEmail(email, password) > 0;
    }
}
